<template>
  <div class="cropper_model">
    <el-dialog title="图片剪裁" width="900px" class="cropper_model_dlg" :visible.sync="dialogVisible" :modal="false" append-to-body  :close-on-click-modal="false" :close-on-press-escape="false">
      <div class="cropper_content">
        <div class="cropper" style="text-align: center;">
          <vueCropper ref="cropper" @imgLoad="handleImgLoad" :img="options.img" :outputSize="options.outputSize" :outputType="options.outputType" :info="options.info" :canScale="options.canScale" :autoCrop="options.autoCrop" :autoCropWidth="options.autoCropWidth" :autoCropHeight="options.autoCropHeight" :fixed="options.fixed" :fixedBox="options.fixedBox" :fixedNumber="options.fixedNumber" @realTime="previewImg">
          </vueCropper>
          <div class="cropper_btns">
            <el-button type="primary" @click="goUpload" size="mini">
              重新上传
            </el-button>
            <el-button @click="rotateLeft"  icon="el-icon-refresh-left" size="mini" title="左旋转"></el-button>
            <el-button @click="rotateRight" icon="el-icon-refresh-right" size="mini" title="右旋转"></el-button>
            <el-button @click="changeScale(1)" icon="el-icon-zoom-in" size="mini" title="放大"></el-button>
            <el-button @click="changeScale(-1)" icon="el-icon-zoom-out"  size="mini" title="缩小"></el-button>
          </div>
        </div>
        <div class="cropper_right">
          <h3>预览</h3>
          <!-- 预览 -->
          <div class="cropper_preview" :style="{
              width: preview.w + 'px',
              height: preview.h + 'px',
              overflow: 'hidden',
              margin: '5px'
            }">
            <div :style="preview.div">
              <img :src="preview.url" :style="preview.img" alt="" />
            </div>
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" size="small" :disabled="!imgLoad" :loading="loading" @click="uploadImg">确定上传</el-button>
      </div>
    </el-dialog>
  </div>
</template>
 
<script>
import { VueCropper } from "vue-cropper"
export default {
  unAutoRegister: true, //不自动注册组件
  components: { VueCropper },
  props: {
    //加载状态
    loading: {
      type: Boolean,
      default: false
    },
    // 裁剪的配置
    setting: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data() {
    return {
      imgLoad: false, // 图片是否加载完成
      dialogVisible: false,
      options: {
        img: "", // 裁剪图片的地址
        outputSize: 1, // 裁剪生成图片的质量
        outputType: "png", // 裁剪生成图片的格式
        info: true, // 裁剪框的大小信息
        canScale: true, // 图片是否允许滚动缩放
        autoCrop: true, // 是否默认生成截图狂
        autoCropWidth: 300, // 默认生成截图框宽度
        autoCropHeight: 300, // 默认生成截图框高度
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [1, 1], // 截图框的宽高比例
        full: true, // 是否输出原图比例的截图
        fixedBox: false, // 固定截图框大小 不允许改变
        canMove: true, // 上传图片是否可以移动
        canMoveBox: true, // 截图框能否拖动
        original: true, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        high: false, // 是否按照设备的dpr输出等比例图片
        infoTrue: true, // true为展示真实输出图片宽高false展示看到的截图框宽高
        maximgSize: 800, // 限制图片最大宽度和高度
        enlarge: 1, // 图片根据截图框输出比例倍数
        mode: "contain" // 图片默认渲染方式(contain, cover, 100px, 100% auto)
      },
      preview: {},
      imgName: "" // 图片名字
    }
  },
  created() {
    this.options = Object.assign(this.options, this.setting)
  },
  methods: {
    // 图片加载完成回调
    handleImgLoad(success, error) {
      if (success) {
        this.imgLoad = true
      } else if (error) {
        this.imgLoad = false
      }
    },
    open(data) {
      this.imgName = data.name || "photo.png"
      this.options.img = window.URL.createObjectURL(data)
      this.dialogVisible = true
    },
    close() {
      this.imgLoad = false
      this.dialogVisible = false
    },
    // base64转图片文件
    dataURLtoFile(dataurl, filename) {
      const arr = dataurl.split(",")
      const mime = arr[0].match(/:(.*?);/)[1]
      const bstr = atob(arr[1])
      let len = bstr.length
      const u8arr = new Uint8Array(len)
      while (len--) {
        u8arr[len] = bstr.charCodeAt(len)
      }
      return new File([u8arr], filename, { type: mime })
    },
    // 左旋转
    rotateLeft() {
      this.$refs.cropper.rotateLeft()
    },
    // 右旋转
    rotateRight() {
      this.$refs.cropper.rotateRight()
    },
    // 放大缩小
    changeScale(num) {
      num = num || 1
      this.$refs.cropper.changeScale(num)
    },
    // 实时预览
    previewImg(data) {
      this.preview = data
    },
    goUpload() {
      // 重新上传
      this.imgLoad = false
      this.$emit("upAgain")
    },
    // 上传图片
    uploadImg() {
      const self = this
      if (self.loading) {
        return
      }
      self.$emit("update:loading", true)
      this.$refs.cropper.getCropData(data => {
        const file = this.dataURLtoFile(data, this.imgName)
        this.$emit("getFile", file)
      })
    }
  }
}
</script>
 
<style lang="scss" scoped>
.cropper_model_dlg {
 ::v-deep .el-dialog__body {
    height: 500px !important;
    .cropper_content {
      width: 100%;
      margin: 0 auto;
      margin-top: 20px;
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
    }
    .cropper {
      width: 400px;
      height: 400px;
      background: yellow;
    }
    .cropper_right {
      width: 400px;
      text-align: center;
    }
    .cropper_preview {
      margin: 0 auto;
      display: inline-block;
      border: 1px solid #ddd;
    }
    .cropper_btns {
      margin-top: 20px;
    }
  }
}
</style>